﻿using System;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace Tapper
{
    public class Table : Character
    {
        private bool m_isPlayerGet;
        private Vector2 m_tableSize;
        private readonly Texture2D m_texture;
        private readonly Vector2 m_tableScale;        
        public readonly TableState m_tableState;
        private ClientState m_clientState;
        public float m_timer;

        public Table(World world, Texture2D texture, Vector2 pos, Vector2 vel, TableState tableState, ClientState clientState) : base(world, texture, pos, vel)
        {
            m_texture     = texture;            
            m_tableState  = tableState;
            m_clientState = clientState;
            m_tableScale  = new Vector2(m_scale, m_scale);
            m_tableSize   = new Vector2(m_texture.Width, m_texture.Height);
           
        }

        public override void Update(GameTime gametime)
        {
            //Todo: Timer para adicionar Entity
            m_timer += (float)gametime.ElapsedGameTime.TotalSeconds;

            if (m_timer > 5.0f)
            {
                foreach (var manager in m_world.m_manager)
                {
                    m_world.AddEntity(manager.Key);
                    m_world.m_manager.Remove(manager.Key);
                    break;
                }
            }
            
            //x MiniMax para o Cliente
            //Procura pelo cliente na sua mesa
            foreach (var client in m_world.m_entities.
                Select(current => current as Client).
                Where(client => client != null).
                Where(client => !client.m_wasRemoved).
                Where(client => client.m_tableState == m_tableState))
            {
                var distance = Math.Abs(client.m_pos.X - m_pos.X);
                //Se o cliente estiver no começo da mesa
                if (distance < 16.0f)
                {                    
                    //client.m_moveDir.X  = 1;                   
                    client.m_getsPlayer   = true; //Flag do cliente, ver classe Client.cs
                    m_isPlayerGet         = client.m_getsPlayer;
                    m_world.m_gameState   = GameState.OnGameOver;
                }
                //x Detectar o final da mesa
                //! Detectado!!!
                else if (client.m_pos.X > m_pos.X + m_tableSize.X)
                {
                    client.m_moveDir.X = 0;                                                            
                    m_world.m_manager.Add(new Client(client.m_world, client.m_texture,client.m_originalPos,client.m_vel,client.m_distanceOnMug,null,client.m_tableState), client.m_tableState);

                    m_world.DelEntity(client.m_mugs);
                    m_world.DelEntity(client);                    
                    m_clientState = ClientState.OutSideBar;
                }
            }
            
            //x Todo Minimax para o Player
            //x player max table, quando é pego pelo cliente
            foreach (var player in m_world.m_entities.
                Select(current => current as Player).
                Where(player => player != null).
                Where(player => player.m_tableState == m_tableState))
            {
                if ((player.m_pos.X > m_pos.X + m_tableSize.X) && (m_isPlayerGet))
                {
                    m_world.DelEntity(player);
                }
                //Limite de tela para o player, final da mesa. 
                else if (player.m_pos.X > m_pos.X + m_tableSize.X)
                {
                    player.m_pos.X = m_pos.X + m_tableSize.X;
                }
                else if ((player.m_pos.X < m_pos.X - 40.0f)) //limite de tela, inicio da mesa mais uma  distancia. 
                {
                    player.m_pos.X = m_pos.X - 40.0f;
                }
                //limite de tela foi refatorado da classe player. 100~ linhas apagadas na respectiva classe
            }


            //x Todo Minimax para o Mug
            foreach(var mug in m_world.m_entities.
                Select(current => current as Mugs).
                Where(mug => mug != null).
                Where(mug => mug.m_tableState == m_tableState))
            {
                switch (mug.m_mugState)
                {
                    case MugState.Returning:
                        foreach (var player in m_world.m_entities.
                            Select(current => current as Player).
                            Where(player => player != null))
                        {
                            if (player.m_tableState != m_tableState)
                            {
                                //Todo Se player estiver na mesma posição. nao pode ter gameOver                                
                                var distance = Math.Abs(mug.m_pos.X - m_pos.X);
                                if (distance < 16.0f)
                                {
                                    m_world.DelEntity(mug);
                                    m_world.m_gameState = GameState.OnGameOver;
                                }
                            }
                        }
                        break;
                    case MugState.Serving:
                        if (mug.m_pos.X > m_pos.X + m_tableSize.X)
                        {
                            m_world.DelEntity(mug);
                            m_world.m_gameState = GameState.OnGameOver;
                        }
                        break;
                }                                
            }
            m_timer = 0;
            base.Update(gametime);
        }

        public override void Draw(GameTime gametime, SpriteBatch spritebatch)
        {            
            spritebatch.Draw(m_texture, m_pos, null, Color.White, 0.0f, Vector2.Zero, m_tableScale, SpriteEffects.None, 0.7f);
        }
    }
}
